Editing shaders

In Kanzi Studio, the shader programs are stored as external files. When you add shaders to the <KanziWorkspace>/Projects/<ProjectName>/Shaders directory of your Kanzi Studio project, Kanzi Studio automatically shows them in the Library > Resource Files > Shaders.

Access to the shader files is useful when you want to change all the stock material types from a fragment-based to vertex- based shaders, or the other way around. If the filenames are the same, to do this, replace the shader files with the correct versions on the file system.

The fastest way to generate your own shading is to find a similar use case in the Kanzi material library, and then modify the shader and material properties, or use shaders from the Phong or PhongTextured material types as a template.

Kanzi Studio shader code editor

You can use Kanzi Studio shader code editor to edit the shader source code. When working with the Kanzi Studio code editor keep in mind that:

Shader attributes

The input for shader programs are vertex attributes and uniforms. The attributes can vary per vertex and are provided to vertex shaders. You can use the uniforms as input to either vertex or fragment shader.

The vertex buffer of a mesh contains also a set of attributes. These vertex buffer attributes are used for sending data to vertex shader.

Kanzi can automatically pass attributes to shader programs, but you can configure these settings manually too.

Vertex attributes have always one of the following semantics and Kanzi automatically recognizes the following names:

Attribute Description
kzPosition position
kzNormal normal
kzTangent tangent
kzWeight weight
kzMatrixIndices matrix palette
kzTextureCoordinate0 texture coordinate
kzTextureCoordinate1 texture coordinate
kzTextureCoordinate2 texture coordinate
kzTextureCoordinate3 texture coordinate
kzColor0 color
kzColor1 color
kzColor2 color
kzColor3 color
kzCustomAttribute0 custom
kzCustomAttribute1 custom
kzCustomAttribute2 custom
kzCustomAttribute3 custom
kzCustomAttribute4 custom
kzCustomAttribute5 custom
kzCustomAttribute6 custom
kzCustomAttribute7 custom

If there is one to one relation between shader attributes and vertex attributes, the attributes are automatically mapped against each other. You can configure the mappings manually to work differently in mesh data. You must use manual mappings if you are using shader attribute names, which are not in the default list.

Shader uniforms

Shader uniforms can receive their data from these data sources:

If the name of the uniform matches with any of the Kanzi default uniforms, Kanzi Engine automatically sends its value to shader program. These uniforms are available by default:

Uniform Description
kzWorldMatrix (mat4) A transformation matrix to transform from local coordinates to world (global) coordinates.
kzCameraMatrix (mat4) A matrix to transform from world (global) coordinates to view (camera) coordinates, that is, applying camera.
kzCameraWorldMatrix (mat4) Pre-multiplied matrix: kzCameraMatrix * kzWorldMatrix
kzProjectionCameraWorldMatrix (mat4) Pre-multiplied matrix: kzProjectionmatrix * kzCameraMatrix * kzWorldMatrix
kzProjectionMatrix (mat4) A matrix to project view coordinates into screen coordinates.
kzNormalMatrix (mat4) A matrix to transform object normals to world coordinates.
kzCameraNormalMatrix(mat4) Pre-multiplied matrix: kzCameraMatrix * kzNormalMatrix
kzCameraPosition (vec3) Camera location in world coordinates.
kzTime (float) Debug timer, 1.0f = 1000 milliseconds.
kzTextureWidth0 (float) Width of texture bound in unit 0.
kzTextureWidth1 (float) Width of texture bound in unit 1.
kzTextureWidth2 (float) Width of texture bound in unit 2.
kzTextureWidth3 (float) Width of texture bound in unit 3.
kzTextureHeight0 (float) Height of texture bound in unit 0.
kzTextureHeight1 (float Height of texture bound in unit 1.
kzTextureHeight2 (float) Height of texture bound in unit 2.
kzTextureHeight3 (float) Height of texture bound in unit 3.
kzMatrixPalette (vec4) Array of 4x3 matrices used in vertex skinning. Each matrix is in form:
[ m00 m01 m02 translate_x]
[ m10 m11 m12 translate_y]
[ m20 m21 m22 translate_z]
kzLightShadowProjectionMatrix (mat4) A transformation for projecting from world coordinates to shadow map texture coordinates [0, 1].

Material uniforms

If the name of the uniform matches any of the property types defined in the material type of the shader, the value is supplied using the properties. At runtime the values for the properties are collected from the rendered material and the lights that match the light properties defined in the material type with possible property overriding.

The names and data types of the uniforms must match with the names and data types of the property types in a material type. Note that the display name of a property type can be different from its real name that is used in this context. See Property types. For example, if the material type has a color property type Diffuse, the shader code must have the following definition:

uniform mediump vec4 Diffuse;

The letters and the case must match in the names. These are the compatible data types from property data type to shader variable data type:

Property data type Shader variable data type
Float float
Vector 2D vec2
Vector 3D vec3
Color vec4
Vector 4D vec4
Matrix 2D mat2
Matrix 3D mat3
Matrix 4D mat4
Texture sampler1D
sampler2D
sampler3D
sampler1DShadow
sampler2DShadow
samplerCube

Structural property types with uniforms

Light property types and group property types are structured property types that contain a set property types inside them. See Property types. These structures are flattened when matching the property types against the shader uniforms. For example DirectionalLight property type consists of property types: DirectionalLightColor, DirectionalLightDirection, and DirectionalLightShadowCaster. A shader program that uses the color and direction of one directional light is:

uniform mediump vec4 DirectionalLightColor;
uniform mediump vec3 DirectionalLightDirection;

Uniform arrays

In addition to the flatting of structured property types the light property types also support uniform arrays for enabling use of multiple lights of the same type. For example, if one shader program uses two directional lights, you must add an array property type into that shader of the material type:

uniform mediump vec4 DirectionalLightColor[2];
uniform mediump vec3 DirectionalLightDirection[2];

Example vertex shader

This is an example of Phong vertex shader used in Gestures example. See Gestures example

attribute vec3 kzPosition;
attribute vec3 kzNormal;
uniform highp mat4 kzProjectionCameraWorldMatrix;
uniform highp mat4 kzWorldMatrix;
uniform highp mat4 kzNormalMatrix;
uniform highp vec3 kzCameraPosition;
uniform mediump vec3 PointLightPosition[2];
uniform mediump vec4 PointLightColor[2];
uniform mediump vec3 PointLightAttenuation[2];

uniform mediump vec4 Ambient;
uniform mediump vec4 Diffuse;
uniform mediump vec4 SpecularColor;
uniform mediump float SpecularExponent;

varying lowp vec3 vAmbDif;
varying lowp vec3 vSpec;

void main()
{
	precision mediump float;

	vec3 pointLightDirection[2];
	vec4 positionWorld = kzWorldMatrix * vec4(kzPosition.xyz, 1.0);
	vec3 V = normalize(positionWorld.xyz - kzCameraPosition);
	vec4 Norm = kzNormalMatrix * vec4(kzNormal, 1.0);
	vec3 N = normalize(Norm.xyz);

	pointLightDirection[0] = positionWorld.xyz - PointLightPosition[0];
	pointLightDirection[1] = positionWorld.xyz - PointLightPosition[1];
    
	vec3 L[2];
	vec3 H[2];
	float LdotN, NdotH;
	float specular;
	vec3 c;
	float d, attenuation;
    
	vAmbDif = vec3(0.0);
	vSpec = vec3(0.0);
    
	L[0] = normalize(-pointLightDirection[0]);
	H[0] = normalize(-V + L[0]);
    
	L[1] = normalize(-pointLightDirection[1]);
	H[1] = normalize(-V + L[1]);

	vAmbDif += Ambient.rgb;
  
	// Apply point light 0.
	{
		LdotN = max(0.0, dot(L[0], N));
		NdotH = max(0.0, dot(N, H[0]));
		specular = pow(NdotH, SpecularExponent);
		c = PointLightAttenuation[0];
		d = length(pointLightDirection[0]);
		attenuation = 1.0 / max(0.001, (c.x + c.y * d + c.z * d * d));
		vAmbDif += (LdotN * Diffuse.rgb) * attenuation * PointLightColor[0].rgb;
		vSpec +=  SpecularColor.rgb * specular * attenuation * PointLightColor[0].rgb;
	}

	// Apply point light 1.
	{
		LdotN = max(0.0, dot(L[1], N));
		NdotH = max(0.0, dot(N, H[1]));
		specular = pow(NdotH, SpecularExponent);
		c = PointLightAttenuation[1];
		d = length(pointLightDirection[1]);
		attenuation = 1.0 / max(0.001, (c.x + c.y * d + c.z * d * d));
		vAmbDif += (LdotN * Diffuse.rgb) * attenuation * PointLightColor[1].rgb;
		vSpec +=  SpecularColor.rgb * specular * attenuation * PointLightColor[1].rgb;
	}

	gl_Position = kzProjectionCameraWorldMatrix * vec4(kzPosition.xyz, 1.0);
}